package top.z.orm.core.osql;

import java.util.List;
import java.util.Map;

/**
 * 支持带占位符的SQL操作.SQL语句是DB能识别的SQL,非面向对象的SQL
 * <p>支持的占位符有 ? 或者 #{param} 或者 #{param%}, 都可以通过PreparedStatement防范SQL注入攻击
 * <p>若是可以,建议使用面向对象的操作方式,如:Suid和SuidRich,可以使用Bee缓存,获取更高的查询效率
 * <br>若没有使用占位符,则传入空数组或Map即可
 * 支持如 name=#{name}, name like #{name%} 的 map 参数形式
 */
public interface PreparedSql {

    /**
     * 通过问号的占位语句查询数据
     * eg: select * from orders where userid = ?
     *
     * @param sql        直接用 ? 作为占位符的 sql 查询语句
     * @param returnType 返回entity的类型
     * @param preValues  按下标顺序给sql的占位符设值的Object数组
     * @return 返回returnType类型的实体List
     */
    <T> List<T> select(String sql, T returnType, Object[] preValues);

    /**
     * 通过问号的占位语句查询数据
     * eg: select * from orders where userid = ?
     *
     * @param sql        直接用 ? 作为占位符的sql查询语句
     * @param returnType 返回 entity 的类型
     * @param preValues  按下标顺序给 sql 的占位符设值的 Object 数组
     * @return 返回 returnType 类型的实体 List
     */
    <T> List<T> select(String sql, T returnType, Object[] preValues, int start, int size);

    /**
     * 通过变量的占位语句查询数据. entity 和 map 都可以向参数传递值, map 可以作为 entity 的补充, 用于传递范围查询等复杂查询的参数
     * eg:select * from orders where userid = #{userid}
     * eg:select * from orders where name like #{name%}
     *
     * @param sqlStr       使用 #{param} 作为占位符的 sql 查询语句
     * @param entity       entity 中非 null 的值, 会转换成 map 的元素作为参数, entity 的字段会自动转成表的列名; entity 也将作用返回结构的类型
     * @param parameterMap map 结构的参数, 通过 map 的 key 与 sqlStr 中变量名对应, 若 map 有元素的 key 与从 entity 转来的一样, 优先使用 map
     * @return 返回与 entity 类型一样的实体 List
     */
    <T> List<T> select(String sqlStr, T entity, Map<String, Object> parameterMap);

    /**
     * 通过变量的占位语句查询数据. entity 和 map 都可以向参数传递值, map 可以作为 entity 的补充, 用于传递范围查询等复杂查询的参数
     * eg:select * from orders where userid = #{userid}
     * eg:select * from orders where name like #{name%}
     *
     * @param sqlStr       使用 #{para} 作为占位符的 sql 查询语句
     * @param entity       entity 中非 null 的值, 会转换成 map 的元素作为参数, entity 的字段会自动转成表的列名; entity 也将作用返回结构的类型
     * @param parameterMap map结构的参数, 通过 map 的 key 与 sqlStr 中变量名对应,  若 map 有元素的 key 与从 entity 转来的一样, 优先使用 map
     * @param start        开始下标(从 0 或 1 开始, eg: MySQL 是 0, Oracle 是 1)
     * @param size         结果集大小, 大于等于 1
     * @return 返回与 entity 类型一样的实体List
     */
    <T> List<T> select(String sqlStr, T entity, Map<String, Object> parameterMap, int start, int size);

    /**
     * 通过问号的占位语句查询数据(只查询部分字段)
     * eg: select * from orders where userid = ?
     *
     * @param sql        直接用 ? 作为占位符的 sql 查询语句
     * @param returnType 返回 entity 的类型
     * @param preValues  按下标顺序给 sql 的占位符设值的 Object 数组
     * @return 返回 returnType 类型的实体 List
     */
    <T> List<T> selectSomeField(String sql, T returnType, Object[] preValues);

    /**
     * 通过问号的占位语句查询数据(只查询部分字段)
     * eg: select * from orders where userid = ?
     *
     * @param sql        直接用 ? 作为占位符的 sql 查询语句
     * @param returnType 返回 entity 的类型
     * @param preValues  按下标顺序给 sql 的占位符设值的 Object 数组
     * @param start      开始下标(从 0 或 1 开始, eg: MySQL 是 0, Oracle 是 1)
     * @param size       结果集大小, 大于等于 1
     * @return 返回 returnType 类型的实体 List
     */
    <T> List<T> selectSomeField(String sql, T returnType, Object[] preValues, int start, int size);

    /**
     * 通过变量的占位语句查询数据(只查询部分字段). entity 和 map 都可以向参数传递值, map 可以作为 entity 的补充, 用于传递范围查询等复杂查询的参数
     * eg:select * from orders where userid = #{userid}
     * eg:select * from orders where name like #{name%}
     *
     * @param sql    使用 #{para} 作为占位符的 sql 查询语句
     * @param entity entity 中非 null 的值, 会转换成 map 的元素作为参数, entity 的字段会自动转成表的列名; entity 也将作用返回结构的类型
     * @param param  map 结构的参数, 通过 map 的 key 与 sql 中变量名对应, 若 map 有元素的 key 与从 entity 转来的一样, 优先使用 map
     * @return 返回与 entity 类型一样的实体 List
     */
    <T> List<T> selectSomeField(String sql, T entity, Map<String, Object> param);

    /**
     * 通过变量的占位语句查询数据(只查询部分字段). entity 和 map 都可以向参数传递值, map 可以作为 entity 的补充, 用于传递范围查询等复杂查询的参数
     * eg:select * from orders where userid = #{userid}
     * eg:select * from orders where name like #{name%}
     *
     * @param sql    使用 #{para} 作为占位符的 sql 查询语句.
     * @param entity entity 中非 null 的值, 会转换成 map 的元素作为参数, entity 的字段会自动转成表的列名; entity 也将作用返回结构的类型
     * @param param  map 结构的参数, 通过 map 的 key 与 sql 中变量名对应, 若map有元素的key与从entity转来的一样,会使用map的.
     * @param start  开始下标(从 0 或 1 开始, eg: MySQL 是 0, Oracle 是 1)
     * @param size   结果集大小, 大于等于 1
     * @return 返回与 entity 类型一样的实体 List
     */
    <T> List<T> selectSomeField(String sql, T entity, Map<String, Object> param, int start, int size);

    /**
     * 用函数查询结果
     * 注意: 因没有与 entity 关联, 不能使用缓存
     *
     * @param sql   SQL select statement
     * @param value 按下标顺序给 sql 的占位符设值的 Object 数组
     * @return 返回函数统计的值, 如果统计的结果集为空, 除了 count 返回 0, 其它都返回空字符
     * @throws ObjSQLException exception
     */
    String selectFun(String sql, Object[] value) throws ObjSQLException;

    /**
     * 用函数查询结果
     * 注意: 因没有与 entity 关联, 不能使用缓存
     *
     * @param sql sql 查询语句
     * @param map map 结构的参数, 通过 map 的 key 与 sql 中变量名对应
     * @return 返回函数统计的值, 如果统计的结果集为空, 除了 count 返回 0, 其它都返回空字符
     * @throws ObjSQLException exception
     */
    String selectFun(String sql, Map<String, Object> map) throws ObjSQLException;

    /**
     * 查询并将每一行结果转成 String 数组
     * 注意: 因没有与 entity 关联, 不能使用缓存
     *
     * @param sql   sql 查询语句
     * @param value 按下标顺序给 sql 的占位符设值的 Object 数组
     * @return 可包含多个 String 数组结构的多条记录的 List
     */
    List<String[]> select(String sql, Object[] value);

    /**
     * 查询并将每一行结果转成 String 数组
     * 注意: 因没有与 entity 关联, 不能使用缓存
     *
     * @param sql   sql 查询语句
     * @param value 按下标顺序给 sql 的占位符设值的 Object 数组
     * @param start 开始下标(从 0 或 1 开始, eg: MySQL 是 0, Oracle 是 1)
     * @param size  结果集大小, 大于等于 1
     * @return 可包含多个 String 数组结构的多条记录的List
     */
    List<String[]> select(String sql, Object[] value, int start, int size);

    /**
     * 查询并将每一行结果转成 String 数组
     * 注意: 因没有与 entity 关联, 不能使用缓存
     *
     * @param sql sql 查询语句
     * @param map 结构的参数, 通过 map 的 key 与 sql 中变量名对应
     * @return 可包含多个 String 数组结构的多条记录的 List
     */
    List<String[]> select(String sql, Map<String, Object> map);

    /**
     * 查询并将每一行结果转成 String 数组
     * 注意: 因没有与 entity 关联, 不能使用缓存
     *
     * @param sql   sql 查询语句
     * @param map   结构的参数, 通过 map 的 key 与 sql 中变量名对应
     * @param start 开始下标(从 0 或 1 开始, eg: MySQL 是 0, Oracle 是 1)
     * @param size  结果集大小, 大于等于 1
     * @return 可包含多个 String 数组结构的多条记录的 List
     */
    List<String[]> select(String sql, Map<String, Object> map, int start, int size);

    /**
     * 用可带问号的占位语句查询结果, 并以 json 格式返回
     * 注意: 因没有与 entity 关联, 不能使用缓存
     *
     * @param sql   sql 查询语句
     * @param value 占位符对应的参数数组
     * @return 返回 json 格式结果集
     */
    String selectJson(String sql, Object[] value);

    /**
     * 用可带问号的占位语句查询结果, 并以 json 格式返回
     * 注意: 因没有与 entity 关联, 不能使用缓存
     *
     * @param sql   sql 查询语句
     * @param value 占位符对应的参数数组
     * @param start 开始下标(从 0 或 1 开始, eg: MySQL 是 0, Oracle 是 1)
     * @param size  结果集大小, 大于等于 1
     * @return 返回 json 格式结果集
     */
    String selectJson(String sql, Object[] value, int start, int size);

    /**
     * 查询结果, 并以 json 格式返回
     * 注意: 因没有与 entity 关联, 不能使用缓存
     *
     * @param sql sql 查询语句
     * @param map 结构的参数, 通过 map 的 key 与 sql 中变量名对应
     * @return 返回 json 格式结果集
     */
    String selectJson(String sql, Map<String, Object> map);

    /**
     * 查询结果, 并以 json 格式返回
     * 注意: 因没有与 entity 关联, 不能使用缓存
     *
     * @param sql   sql 查询语句
     * @param map   占位符对应的参数
     * @param start 开始下标(从 0 或 1 开始, eg: MySQL 是 0, Oracle 是 1)
     * @param size  结果集大小, 大于等于 1
     * @return 返回 json 格式结果集
     */
    String selectJson(String sql, Map<String, Object> map, int start, int size);

    /**
     * 查询结果, 并以 json 格式返回
     * 注意: 因没有与 entity 关联, 不能使用缓存
     *
     * @param sql sql 查询语句
     * @return 返回 json 格式结果集
     */
    String selectJson(String sql);

    /**
     * 通过无参数的 sql 查询语句数据
     * 注意: 因没有与 entity 关联, 不能使用缓存
     * eg: select * from orders where userid = 10001
     *
     * @param sql sql 查询语句
     * @return 返回 returnType 类型的实体 List
     */
    List<String[]> select(String sql);

    /**
     * 用函数查询结果
     * 注意: 因没有与 entity 关联, 不能使用缓存
     *
     * @param sql sql 查询语句
     * @return 返回函数统计的值. 如果统计的结果集为空, 除了 count 返回 0, 其它都返回空字符
     */
    String selectFun(String sql);

}